﻿// ----------------------------------------------------------------------------------
// Microsoft Developer & Platform Evangelism
// 
// Copyright (c) Microsoft Corporation. All rights reserved.
// 
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// ----------------------------------------------------------------------------------
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
// ----------------------------------------------------------------------------------

#region File Description
//-----------------------------------------------------------------------------
// AudioManager.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OggSharp;
using System.IO;
using System.Diagnostics;
using System.IO.IsolatedStorage;
#endregion

namespace BaoVeThanhDia
{
    /// <summary>
    /// Component that manages audio playback for all sounds.
    /// </summary>
    public class AudioManager
    {
        #region Singleton
        private static AudioManager audioManager;
        private static void WriteWave(BinaryWriter writer, int channels, int rate, byte[] data)
        {

            writer.Write(new char[4] { 'R', 'I', 'F', 'F' });
            writer.Write((int)(36 + data.Length));
            writer.Write(new char[4] { 'W', 'A', 'V', 'E' });

            writer.Write(new char[4] { 'f', 'm', 't', ' ' });
            writer.Write((int)16);
            writer.Write((short)1);
            writer.Write((short)channels);
            writer.Write((int)rate);
            writer.Write((int)(rate * ((16 * channels) / 8)));
            writer.Write((short)((16 * channels) / 8));
            writer.Write((short)16);

            writer.Write(new char[4] { 'd', 'a', 't', 'a' });
            writer.Write((int)data.Length);
            writer.Write(data);
        }
        #endregion

        #region Audio Data
        private SoundEffectInstance musicSound;
        public static bool IsSoundOn = true;
        public static bool IsVibrateOn = true;
        private Dictionary<string, SoundEffectInstance> soundBank;
        #endregion

        #region Initialization Methods

        public static void Initialize()
        {
            if (audioManager == null)
            {
                audioManager = new AudioManager();
                audioManager.soundBank = new Dictionary<string, SoundEffectInstance>();
            }
        }
        /// <summary>
        /// Initialize the static AudioManager functionality.
        /// </summary>
        /// <param name="game">The game that this component will be attached to.</param>

        #endregion

        #region Loading Methodes
        /// <summary>
        /// Loads a sounds and organizes them for future usage
        /// </summary>
        /// 
        public static void LoadVibrateState()
        {
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
            String myString = "";
            if (storage.FileExists("Vibrate.txt"))
            {
                IsolatedStorageFileStream fileStream = storage.OpenFile("Vibrate.txt", FileMode.Open,
                     FileAccess.Read, FileShare.Read /*, 
                    FileAccess.Read*/);
                using (StreamReader reader = new StreamReader(fileStream))
                {
                    myString = reader.ReadLine();
                    myString = myString.Trim().ToString();
                    if (myString.Equals("True"))
                    {
                        AudioManager.IsVibrateOn = true;
                    }
                    if (myString.Equals("False"))
                    {
                        AudioManager.IsVibrateOn = false;

                    }
                    //                     AudioManager.IsSoundOn = Boolean.Parse(myString);

                    reader.Close();
                    reader.Dispose();
                }
                fileStream.Close();
                fileStream.Dispose();

            }
            Debug.WriteLine("Vibrate State Load : " + myString);
        }
        public static void SaveVibrateState()
        {
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
            String myString = "";

            FileStream stream = storage.OpenFile("Vibrate.txt", FileMode.Create); // Open a file in Create mode
            StreamWriter writer = new StreamWriter(stream);
            if (AudioManager.IsVibrateOn)
            {
                myString = "True";
            }
            else myString = "False";
            writer.Write(myString);
            writer.Close();
            writer.Dispose();
            stream.Close();
            stream.Dispose();


            storage.Dispose();


            Debug.WriteLine("Vibrate State Save : " + myString);
        }
        public static void LoadSoundState()
        {
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
            String myString = "";
            if (storage.FileExists("Audio.txt"))
            {
                IsolatedStorageFileStream fileStream = storage.OpenFile("Audio.txt", FileMode.Open,
                     FileAccess.Read, FileShare.Read /*, 
                    FileAccess.Read*/);
                using (StreamReader reader = new StreamReader(fileStream))
                {
                    myString = reader.ReadLine();
                    myString = myString.Trim().ToString();
                    if (myString.Equals("True"))
                    {
                        AudioManager.IsSoundOn = true;
                    }
                    if (myString.Equals("False"))
                    {
                        AudioManager.IsSoundOn = false;

                    }
                    //                     AudioManager.IsSoundOn = Boolean.Parse(myString);

                    reader.Close();
                    reader.Dispose();
                }
                fileStream.Close();
                fileStream.Dispose();

            }
            Debug.WriteLine("Sound State Load : " + myString);
        }
        public static void SaveSoundState()
        {
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
            String myString = "";

            FileStream stream = storage.OpenFile("Audio.txt", FileMode.Create); // Open a file in Create mode
            StreamWriter writer = new StreamWriter(stream);
            if (AudioManager.IsSoundOn)
            {
                myString = "True";
            }
            else myString = "False";
            writer.Write(myString);
            writer.Close();
            writer.Dispose();
            stream.Close();
            stream.Dispose();


            storage.Dispose();


            Debug.WriteLine("Sound State Save : " + myString);
        }
        public static void LoadSounds(string link)
        {
            if (!audioManager.soundBank.ContainsKey(link))
            {
                string soundLocation = "Assets/song/";
                OggDecoder decoder = new OggDecoder(); decoder.Initialize(TitleContainer.OpenStream(soundLocation + link));
                byte[] data = decoder.SelectMany(chunk => chunk.Bytes.Take(chunk.Length)).ToArray();
                SoundEffect soundEffect;
                using (MemoryStream stream = new MemoryStream())

                using (BinaryWriter writer = new BinaryWriter(stream))
                {
                    WriteWave(writer, decoder.Stereo ? 2 : 1, decoder.SampleRate, data);
                    stream.Position = 0;
                    soundEffect = SoundEffect.FromStream(stream);
                }
                audioManager.soundBank.Add(
                    link, soundEffect.CreateInstance());
            }
        }
        #endregion

        #region Sound Methods
        /// <summary>
        /// Plays a sound by name.
        /// </summary>
        /// <param name="soundName">The name of the sound to play</param>
        public static void PlaySound(string soundName)
        {
            // If the sound exists, start it
            if (IsSoundOn)
            {

                if (audioManager.soundBank.ContainsKey(soundName))
                {
                    Debug.WriteLine("play sound " + soundName);
                    audioManager.soundBank[soundName].Play();
                }
            }
        }

        /// <summary>
        /// Plays a sound by name.
        /// </summary>
        /// <param name="soundName">The name of the sound to play</param>
        /// <param name="isLooped">Indicates if the sound should loop</param>
        public static void PlaySound(string soundName, bool isLooped)
        {
            // If the sound exists, start it
            if (IsSoundOn)
            {
                if (audioManager.soundBank.ContainsKey(soundName))
                {
                    if (audioManager.soundBank[soundName].IsLooped != isLooped)
                        audioManager.soundBank[soundName].IsLooped = isLooped;

                    audioManager.soundBank[soundName].Play();
                }
            }
        }


        public static void PlaySound(string soundName, bool isLooped, float amLuong)
        {
            // If the sound exists, start it
            if (IsSoundOn)
            {

                if (audioManager.soundBank.ContainsKey(soundName))
                {
                    if (audioManager.soundBank[soundName].IsLooped != isLooped)
                        audioManager.soundBank[soundName].IsLooped = isLooped;
                    audioManager.soundBank[soundName].Play();
                    audioManager.soundBank[soundName].Volume = amLuong;

                }
            }
        }

        /// <summary>
        /// Stops a sound mid-play. If the sound is not playing, this
        /// method does nothing.
        /// </summary>
        /// <param name="soundName">The name of the sound to stop</param>
        public static void StopSound(string soundName)
        {
            // If the sound exists, stop it
            if (audioManager.soundBank.ContainsKey(soundName))
                audioManager.soundBank[soundName].Stop();
        }

        /// <summary>
        /// Stops a sound mid-play. If the sound is not playing, this
        /// method does nothing.
        /// </summary>
        /// <param name="soundName">The name of the sound to stop</param>
        public static void StopSounds()
        {
            var soundEffectInstances = from sound in audioManager.soundBank.Values
                                       where sound.State != SoundState.Stopped
                                       select sound;

            foreach (var soundeffectInstance in soundEffectInstances)
                soundeffectInstance.Stop();
        }

        /// <summary>
        /// Pause or Resume all sounds to support pause screen
        /// </summary>
        /// <param name="isPause">Should pause or resume?</param>
        public static void PauseResumeSounds(bool isPause)
        {
            SoundState state = isPause ? SoundState.Paused : SoundState.Playing;

            var soundEffectInstances = from sound in audioManager.soundBank.Values
                                       where sound.State == state
                                       select sound;

            foreach (var soundeffectInstance in soundEffectInstances)
            {
                if (isPause)
                    soundeffectInstance.Play();
                else
                    soundeffectInstance.Pause();
            }
        }
        /// <summary>
        /// Play music by sound name.
        /// </summary>
        /// <param name="musicSoundName">The name of the music sound</param>
        public static void PlayMusic(string musicSoundName)
        {
            // Stop the old music sound
            if (audioManager.musicSound != null)
                audioManager.musicSound.Stop(true);

            // If the music sound exists
            if (audioManager.soundBank.ContainsKey(musicSoundName))
            {
                // Get the instance and start it
                audioManager.musicSound = audioManager.soundBank[musicSoundName];
                if (!audioManager.musicSound.IsLooped)
                    audioManager.musicSound.IsLooped = true;
                audioManager.musicSound.Play();
            }
        }
        #endregion

    }
}
